package xml;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import xml.jxb.ObjectFactory;
import xml.jxb.Project;
import org.xml.sax.SAXException;

/**
 * <p>Java class for parsing and storing xml-models in SysUtvikling project
 * <p>XML models parses into java classes hierarchy with main class "Project"
 * that contains all another elements of model
 *
 * @author 490501
 * @version 1.0.1.a
 * @since 1.0.0.a
 */
public class Parser {

    private JAXBContext js;
    private Unmarshaller unmarshaller;
    private javax.xml.bind.Marshaller marshaller;
    protected JAXBElement<Project> _root;
    protected Project root;

    /**
     * <p>Create new instance of xml parser with default character encoding
     * <b>UTF-8</b>
     *
     * @throws JAXBException if any JAXBException occurs
     * @throws SAXException if any SAXException occurs during validation of xml
     * modell
     */
    public Parser(String _pathToSchema) throws JAXBException, SAXException {
        if(_pathToSchema == null){
            _pathToSchema = Parser.class.getResource("v1s.xsd").getPath();
        }
        SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = sf.newSchema(new File(_pathToSchema));
        this.js = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName());
        this.unmarshaller = js.createUnmarshaller();
        this.unmarshaller.setSchema(schema);
        this.marshaller = js.createMarshaller();
        this.marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8");
        this.marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        this.marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_SCHEMA_LOCATION, "v1s.xsd");
    }

    /**
     * <p>Load xml model into the parser
     *
     * @param _path path to xml document that will be loaded into parser
     * @throws JAXBException if any JAXBException occurs
     * @since 1.0.0.a
     */
    public void loadXML(String _path) throws JAXBException {
        this._root = (JAXBElement<Project>) unmarshaller.unmarshal(new File(_path));
        this.root = _root.getValue();
    }

    /**
     * <p> load project from input stream
     * @param is input stream
     * @throws JAXBException if any JAXBException occurs
     * @since 1.0.1.a
     */
    public void loadXML(InputStream is) throws JAXBException {
        this._root = (JAXBElement<Project>) unmarshaller.unmarshal(is);
        this.root = _root.getValue();
    }

    /**
     * <p>Save xml modell to a file
     *
     * @param _path path to file where xml modell will be stored
     * @throws JAXBException if any JAXBException occurs
     */
    public void storeXML(String _path) throws JAXBException {
        JAXBElement _e = new ObjectFactory().createProject(this.root);
        this.marshaller.marshal(_e, new File(_path));
    }
    
    /**
     * 
     * @param _os
     * @throws JAXBException 
     */
    public void StoreXML(OutputStream _os) throws JAXBException{
        JAXBElement _e = new ObjectFactory().createProject(this.root);
        this.marshaller.marshal(_e, _os);
    }

    /**
     * Load project from Project class into xml parser
     *
     * @param _proj
     */
    public void loadProject(Project _proj) {
        this._root = null;
        this.root = null;
        this.root = _proj;
    }

    /**
     * Gets the reference to Project class loaded into parser
     *
     * @return
     */
    public Project getProject() {
        return root;
    }
}
